package workflow

import (
	"bytes"
	"fmt"
	"strconv"
)

type WfidFunc func(interface{}) (int, error)

var wfidFuncMap map[string]WfidFunc

func SetWfidFunc(funcName string, wfidFunc WfidFunc) {
	if wfidFuncMap == nil {
		wfidFuncMap = make(map[string]WfidFunc)
	}
	wfidFuncMap[funcName] = wfidFunc
}

type EntityInfo struct {
	Wfids    []int
	WfidFunc WfidFunc
	MgMap    map[int]string
}

func (ei *EntityInfo) WfidsToString() string {
	if len(ei.Wfids) == 0 {
		return ""
	}
	var sb bytes.Buffer
	for _, wfid := range ei.Wfids {
		sb.WriteString(strconv.Itoa(wfid))
		sb.WriteString(",")
	}
	sb.Truncate(sb.Len() - 1)
	return sb.String()
}
func (ei *EntityInfo) MgMapToString() string {
	if len(ei.MgMap) == 0 {
		return ""
	}
	var sb bytes.Buffer
	for k, v := range ei.MgMap {
		sb.WriteString(strconv.Itoa(k))
		sb.WriteString(":")
		sb.WriteString(v)
		sb.WriteString(";")
	}
	sb.Truncate(sb.Len() - 1)
	return sb.String()
}

var eiMap map[string]*EntityInfo = make(map[string]*EntityInfo)

func GetEntityInfo(entityName string) (ei *EntityInfo, err error) {
	var ok bool
	if ei, ok = eiMap[entityName]; ok {
		return
	}
	ei = &EntityInfo{
		Wfids: make([]int, 0, 3),
		MgMap: make(map[int]string),
	}
	var wfidf WfidFunc
	for _, wf := range wfContext.WorkFlows {
		if wf.Entity == entityName {
			ei.Wfids = append(ei.Wfids, wf.ID)
			if wf.Manager != "" {
				ei.MgMap[wf.ID] = wf.Manager
			}
			if wf.GetWfidFunc != "" && wfidf == nil {
				var ok bool
				wfidf, ok = wfidFuncMap[wf.GetWfidFunc]
				if !ok || wfidf == nil {
					err = fmt.Errorf("流程%s指定的getWfidFunc:%s在列表中不存在,是否忘记设置", wf.Name, wf.GetWfidFunc)
					return
				}
			}
		}
	}
	wlen := len(ei.Wfids)
	if wlen == 0 {
		err = fmt.Errorf("没有找到实体%s对应的流程", entityName)
		return
	}
	if wfidf == nil && wlen > 1 {
		err = fmt.Errorf("实体%s对应%d个流程, 必须指定getWfidFunc函数", entityName, wlen)
		return
	}
	if wfidf == nil {
		ei.WfidFunc = func(obj interface{}) (wfid int, err error) {
			return ei.Wfids[0], nil
		}
	} else {
		ei.WfidFunc = wfidf
	}
	eiMap[entityName] = ei
	return
}
